"""摄像头相关API路由"""

from flask import Blueprint, request, jsonify, Response
import logging
import cv2
import time
import threading
import io
from PIL import Image
import base64

from video_processing import camera_manager
from database import db_service

# 创建蓝图
cameras_bp = Blueprint('cameras', __name__, url_prefix='/api/cameras')

# 配置日志
# 导入必要的模块
from datetime import datetime
from flask import request, jsonify, Response
from .auth import token_required
import json
import logging

# 获取日志记录器
logger = logging.getLogger('api.cameras')

# 延迟初始化，避免循环导入
_camera_manager = None

def _get_camera_manager():
    global _camera_manager
    if _camera_manager is None:
        from video_processing import camera_manager as cm
        _camera_manager = cm
    return _camera_manager

def _get_video_manager():
    """获取视频管理器实例"""
    camera_mgr = _get_camera_manager()
    return camera_mgr.get_video_manager() if hasattr(camera_mgr, 'get_video_manager') else None

# 视频流生成器字典
stream_generators = {}

@cameras_bp.route('/', methods=['GET'])
@token_required
def get_all_cameras():
    """获取所有摄像头列表
    
    GET /api/cameras
    
    返回所有已配置的摄像头信息
    """
    try:
        # 从数据库获取摄像头配置
        cameras = db_service.get_all_cameras()
        
        # 获取视频管理器中的状态信息
        video_mgr = _get_video_manager()
        statuses = video_mgr.get_all_camera_status() if video_mgr else {}
        
        # 合并配置和状态信息
        camera_list = []
        for camera in cameras:
            camera_dict = camera.to_dict() if hasattr(camera, 'to_dict') else dict(camera)
            # 添加状态信息
            if str(camera_dict.get('id')) in statuses:
                camera_dict['status'] = statuses[str(camera_dict.get('id'))]
            else:
                camera_dict['status'] = {'status': 'unknown'}
            
            camera_list.append(camera_dict)
        
        return jsonify({
            "cameras": camera_list,
            "total": len(camera_list),
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"获取摄像头列表失败: {str(e)}")
        return jsonify({"error": "获取摄像头列表失败"}), 500

@cameras_bp.route('/<int:camera_id>', methods=['GET'])
@token_required
def get_camera_detail(camera_id):
    """获取单个摄像头详情
    
    GET /api/cameras/<camera_id>
    
    参数:
    - camera_id: 摄像头ID
    
    返回摄像头的详细配置和状态信息
    """
    try:
        # 从数据库获取摄像头配置
        camera = db_service.get_camera_by_id(camera_id)
        if not camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 转换为字典
        camera_dict = camera.to_dict() if hasattr(camera, 'to_dict') else dict(camera)
        
        # 获取视频管理器中的状态信息
        video_mgr = _get_video_manager()
        if video_mgr:
            status = video_mgr.get_camera_status(camera_id)
            if status:
                camera_dict['status'] = status
            else:
                camera_dict['status'] = {'status': 'unknown'}
        else:
            camera_dict['status'] = {'status': 'service_unavailable'}
        
        return jsonify(camera_dict), 200
        
    except Exception as e:
        logger.error(f"获取摄像头详情失败: {str(e)}")
        return jsonify({"error": "获取摄像头详情失败"}), 500

@cameras_bp.route('/', methods=['POST'])
@token_required
def add_camera():
    """添加新摄像头
    
    POST /api/cameras
    
    请求体:
    {
        "name": "摄像头名称",
        "url": "rtsp://摄像头地址",
        "location": "安装位置",
        "description": "摄像头描述",
        "enabled": true,
        "config": {摄像头配置对象}
    }
    """
    try:
        # 获取请求数据
        data = request.get_json()
        
        # 验证必要字段
        required_fields = ['name', 'url']
        for field in required_fields:
            if field not in data:
                return jsonify({"error": f"缺少必要字段: {field}"}), 400
        
        # 添加摄像头到数据库
        camera_id = db_service.add_camera(
            name=data['name'],
            url=data['url'],
            location=data.get('location', ''),
            description=data.get('description', ''),
            enabled=data.get('enabled', True),
            config=json.dumps(data.get('config', {})) if isinstance(data.get('config'), dict) else data.get('config', '{}'),
            created_by=request.user_id
        )
        
        # 如果启用，尝试启动摄像头
        if data.get('enabled', True):
            video_mgr = _get_video_manager()
            if video_mgr:
                # 先获取摄像头配置
                camera = db_service.get_camera_by_id(camera_id)
                camera_dict = camera.to_dict() if hasattr(camera, 'to_dict') else dict(camera)
                
                # 启动摄像头
                try:
                    if hasattr(video_mgr, 'add_camera'):
                        video_mgr.add_camera(camera_dict)
                    if hasattr(video_mgr, 'start_camera'):
                        video_mgr.start_camera(camera_id)
                except Exception as e:
                    logger.warning(f"启动新摄像头失败: {str(e)}")
        
        return jsonify({
            "message": "摄像头添加成功",
            "camera_id": camera_id,
            "timestamp": datetime.now().isoformat()
        }), 201
        
    except Exception as e:
        logger.error(f"添加摄像头失败: {str(e)}")
        return jsonify({"error": "添加摄像头失败"}), 500

@cameras_bp.route('/<int:camera_id>', methods=['PUT'])
@token_required
def update_camera(camera_id):
    """更新摄像头配置
    
    PUT /api/cameras/<camera_id>
    
    请求体: 与添加摄像头类似，但只包含需要更新的字段
    """
    try:
        # 获取请求数据
        data = request.get_json()
        
        # 检查摄像头是否存在
        existing_camera = db_service.get_camera_by_id(camera_id)
        if not existing_camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 更新数据库中的摄像头信息
        update_data = {
            'updated_at': datetime.now(),
            'updated_by': request.user_id
        }
        
        # 添加需要更新的字段
        for field in ['name', 'url', 'location', 'description', 'enabled']:
            if field in data:
                update_data[field] = data[field]
        
        # 处理配置字段
        if 'config' in data:
            update_data['config'] = json.dumps(data['config']) if isinstance(data['config'], dict) else data['config']
        
        # 执行更新
        db_service.update_camera(camera_id, update_data)
        
        # 更新视频管理器中的摄像头配置
        video_mgr = _get_video_manager()
        if video_mgr:
            # 获取更新后的摄像头配置
            updated_camera = db_service.get_camera_by_id(camera_id)
            camera_dict = updated_camera.to_dict() if hasattr(updated_camera, 'to_dict') else dict(updated_camera)
            
            # 更新并重启摄像头
            try:
                # 先停止摄像头
                if hasattr(video_mgr, 'stop_camera'):
                    video_mgr.stop_camera(camera_id)
                # 更新配置
                if hasattr(video_mgr, 'update_camera'):
                    video_mgr.update_camera(camera_id, camera_dict)
                # 如果启用，重新启动
                if data.get('enabled', True) and hasattr(video_mgr, 'start_camera'):
                    video_mgr.start_camera(camera_id)
            except Exception as e:
                logger.warning(f"更新摄像头运行时配置失败: {str(e)}")
        
        return jsonify({
            "message": "摄像头更新成功",
            "camera_id": camera_id,
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"更新摄像头失败: {str(e)}")
        return jsonify({"error": "更新摄像头失败"}), 500

@cameras_bp.route('/<int:camera_id>', methods=['DELETE'])
@token_required
def delete_camera(camera_id):
    """删除摄像头
    
    DELETE /api/cameras/<camera_id>
    
    参数:
    - camera_id: 摄像头ID
    """
    try:
        # 检查摄像头是否存在
        existing_camera = db_service.get_camera_by_id(camera_id)
        if not existing_camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 从视频管理器中移除摄像头
        video_mgr = _get_video_manager()
        if video_mgr:
            try:
                if hasattr(video_mgr, 'stop_camera'):
                    video_mgr.stop_camera(camera_id)
                if hasattr(video_mgr, 'remove_camera'):
                    video_mgr.remove_camera(camera_id)
            except Exception as e:
                logger.warning(f"从视频管理器移除摄像头失败: {str(e)}")
        
        # 从数据库中删除
        db_service.delete_camera(camera_id)
        
        return jsonify({
            "message": "摄像头删除成功",
            "camera_id": camera_id,
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"删除摄像头失败: {str(e)}")
        return jsonify({"error": "删除摄像头失败"}), 500

@cameras_bp.route('/<int:camera_id>/start', methods=['POST'])
@token_required
def start_camera(camera_id):
    """启动摄像头
    
    POST /api/cameras/<camera_id>/start
    
    启动指定的摄像头进行视频处理
    """
    try:
        # 检查摄像头是否存在
        existing_camera = db_service.get_camera_by_id(camera_id)
        if not existing_camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 更新摄像头状态为启用
        db_service.update_camera(camera_id, {'enabled': True})
        
        # 从视频管理器启动摄像头
        video_mgr = _get_video_manager()
        if not video_mgr:
            return jsonify({"error": "视频管理器未启动"}), 503
        
        # 获取摄像头配置
        camera_dict = existing_camera.to_dict() if hasattr(existing_camera, 'to_dict') else dict(existing_camera)
        
        # 确保摄像头在视频管理器中
        if hasattr(video_mgr, 'has_camera'):
            if not video_mgr.has_camera(camera_id):
                if hasattr(video_mgr, 'add_camera'):
                    video_mgr.add_camera(camera_dict)
        
        # 启动摄像头
        success = False
        if hasattr(video_mgr, 'start_camera'):
            success = video_mgr.start_camera(camera_id)
        
        if success:
            return jsonify({
                "message": "摄像头启动成功",
                "camera_id": camera_id,
                "timestamp": datetime.now().isoformat()
            }), 200
        else:
            return jsonify({"error": "摄像头启动失败"}), 500
            
    except Exception as e:
        logger.error(f"启动摄像头失败: {str(e)}")
        return jsonify({"error": "启动摄像头失败"}), 500

@cameras_bp.route('/<int:camera_id>/stop', methods=['POST'])
@token_required
def stop_camera(camera_id):
    """停止摄像头
    
    POST /api/cameras/<camera_id>/stop
    
    停止指定的摄像头视频处理
    """
    try:
        # 检查摄像头是否存在
        existing_camera = db_service.get_camera_by_id(camera_id)
        if not existing_camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 更新摄像头状态为禁用
        db_service.update_camera(camera_id, {'enabled': False})
        
        # 从视频管理器停止摄像头
        video_mgr = _get_video_manager()
        if video_mgr and hasattr(video_mgr, 'stop_camera'):
            video_mgr.stop_camera(camera_id)
        
        return jsonify({
            "message": "摄像头停止成功",
            "camera_id": camera_id,
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"停止摄像头失败: {str(e)}")
        return jsonify({"error": "停止摄像头失败"}), 500

@cameras_bp.route('/<int:camera_id>/snapshot', methods=['GET'])
@token_required
def get_camera_snapshot(camera_id):
    """获取摄像头快照
    
    GET /api/cameras/<camera_id>/snapshot
    
    获取指定摄像头的当前画面
    """
    try:
        # 从视频管理器获取快照
        video_mgr = _get_video_manager()
        if not video_mgr:
            return jsonify({"error": "视频管理器未启动"}), 503
        
        # 检查摄像头是否在运行
        is_running = False
        if hasattr(video_mgr, 'has_camera') and hasattr(video_mgr, 'is_camera_running'):
            is_running = video_mgr.has_camera(camera_id) and video_mgr.is_camera_running(camera_id)
        
        if not is_running:
            return jsonify({"error": "摄像头未运行"}), 400
        
        # 获取快照
        snapshot_data = None
        if hasattr(video_mgr, 'get_camera_snapshot'):
            snapshot_data = video_mgr.get_camera_snapshot(camera_id)
        
        if snapshot_data:
            return jsonify({
                "snapshot": snapshot_data,
                "camera_id": camera_id,
                "timestamp": datetime.now().isoformat()
            }), 200
        else:
            return jsonify({"error": "获取快照失败"}), 500
            
    except Exception as e:
        logger.error(f"获取摄像头快照失败: {str(e)}")
        return jsonify({"error": "获取摄像头快照失败"}), 500

@cameras_bp.route('/<int:camera_id>/stats', methods=['GET'])
@token_required
def get_camera_stats(camera_id):
    """获取摄像头统计信息
    
    GET /api/cameras/<camera_id>/stats
    
    获取指定摄像头的运行统计信息
    """
    try:
        # 从视频管理器获取统计信息
        video_mgr = _get_video_manager()
        if not video_mgr:
            return jsonify({"error": "视频管理器未启动"}), 503
        
        # 获取摄像头状态
        status = None
        if hasattr(video_mgr, 'get_camera_status'):
            status = video_mgr.get_camera_status(camera_id)
        
        if status and 'stats' in status:
            return jsonify({
                "stats": status['stats'],
                "camera_id": camera_id,
                "timestamp": datetime.now().isoformat()
            }), 200
        else:
            return jsonify({"error": "获取摄像头统计信息失败"}), 404
            
    except Exception as e:
        logger.error(f"获取摄像头统计信息失败: {str(e)}")
        return jsonify({"error": "获取摄像头统计信息失败"}), 500

@cameras_bp.route('/start-all', methods=['POST'])
@token_required
def start_all_cameras():
    """启动所有摄像头
    
    POST /api/cameras/start-all
    
    启动所有已启用的摄像头
    """
    try:
        # 获取所有启用的摄像头
        enabled_cameras = db_service.get_cameras_by_enabled(True)
        
        # 从视频管理器启动摄像头
        video_mgr = _get_video_manager()
        if not video_mgr:
            return jsonify({"error": "视频管理器未启动"}), 503
        
        results = {
            "total": len(enabled_cameras),
            "success": 0,
            "failed": 0,
            "failed_cameras": []
        }
        
        # 逐个启动摄像头
        for camera in enabled_cameras:
            camera_id = camera.id if hasattr(camera, 'id') else camera.get('id')
            try:
                camera_dict = camera.to_dict() if hasattr(camera, 'to_dict') else dict(camera)
                
                # 确保摄像头在视频管理器中
                if hasattr(video_mgr, 'has_camera'):
                    if not video_mgr.has_camera(camera_id):
                        if hasattr(video_mgr, 'add_camera'):
                            video_mgr.add_camera(camera_dict)
                
                # 启动摄像头
                success = False
                if hasattr(video_mgr, 'start_camera'):
                    success = video_mgr.start_camera(camera_id)
                    
                if success:
                    results["success"] += 1
                else:
                    results["failed"] += 1
                    results["failed_cameras"].append(camera_id)
            except Exception as e:
                logger.warning(f"启动摄像头 {camera_id} 失败: {str(e)}")
                results["failed"] += 1
                results["failed_cameras"].append(camera_id)
        
        return jsonify({
            "message": "批量启动摄像头完成",
            "results": results,
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"批量启动摄像头失败: {str(e)}")
        return jsonify({"error": "批量启动摄像头失败"}), 500

@cameras_bp.route('/stop-all', methods=['POST'])
@token_required
def stop_all_cameras():
    """停止所有摄像头
    
    POST /api/cameras/stop-all
    
    停止所有运行中的摄像头
    """
    try:
        # 从视频管理器停止所有摄像头
        video_mgr = _get_video_manager()
        if not video_mgr:
            return jsonify({"error": "视频管理器未启动"}), 503
        
        # 停止所有摄像头
        if hasattr(video_mgr, 'stop_all_cameras'):
            video_mgr.stop_all_cameras()
        
        # 更新数据库中所有摄像头的状态为禁用
        if hasattr(db_service, 'update_all_cameras'):
            db_service.update_all_cameras({'enabled': False})
        
        return jsonify({
            "message": "所有摄像头已停止",
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"停止所有摄像头失败: {str(e)}")
        return jsonify({"error": "停止所有摄像头失败"}), 500

# 视频流相关的端点
@cameras_bp.route('/<camera_id>/stream', methods=['GET'])
@token_required
def get_camera_stream(camera_id):
    """获取摄像头视频流
    
    GET /api/cameras/<camera_id>/stream
    
    获取指定摄像头的视频流
    """
    try:
        # 检查摄像头是否存在
        existing_camera = db_service.get_camera_by_id(camera_id)
        if not existing_camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 检查摄像头是否在运行
        video_mgr = _get_video_manager()
        if not video_mgr:
            return jsonify({"error": "视频管理器未启动"}), 503
        
        # 检查摄像头是否在运行
        is_running = video_mgr.is_camera_active(str(camera_id))
        
        if not is_running:
            return jsonify({"error": "摄像头未运行"}), 400
        
        # 生成流URL或令牌
        stream_url = f"/api/cameras/{camera_id}/video_feed"
        
        return jsonify({
            "stream_url": stream_url,
            "camera_id": camera_id,
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"获取摄像头视频流失败: {str(e)}")
        return jsonify({"error": "获取摄像头视频流失败"}), 500

@cameras_bp.route('/<camera_id>/video_feed', methods=['GET'])
def video_feed(camera_id):
    """视频流推送端点
    
    GET /api/cameras/<camera_id>/video_feed
    
    推送MJPEG格式的视频流
    """
    try:
        # 从视频管理器获取视频帧生成器
        video_mgr = _get_video_manager()
        if not video_mgr:
            return jsonify({"error": "视频流不可用"}), 503
        
        # 检查摄像头是否在运行
        is_running = video_mgr.is_camera_active(str(camera_id))
        
        if not is_running:
            return jsonify({"error": "摄像头未运行"}), 400
        
        # 生成视频流
        def generate():
            import cv2
            import io
            import time
            import numpy as np
            from PIL import Image
            
            while True:
                try:
                    # 获取摄像头快照作为视频帧
                    frame = video_mgr.get_camera_snapshot(str(camera_id))
                    
                    if frame is None:
                        # 如果没有获取到帧，使用空帧
                        # 创建一个简单的灰色帧作为替代
                        empty_frame = cv2.imread('api/static/images/placeholder.jpg') if os.path.exists('api/static/images/placeholder.jpg') else None
                        if empty_frame is None:
                            # 如果没有占位图像，创建一个空白图像
                            empty_frame = cv2.imread('static/images/placeholder.jpg') if os.path.exists('static/images/placeholder.jpg') else None
                        if empty_frame is None:
                            # 如果仍然没有占位图像，创建一个简单的黑色图像
                            empty_frame = cv2.UMat(np.zeros((480, 640, 3), dtype=np.uint8))
                        frame = empty_frame
                    
                    # 检查frame类型并转换为JPEG
                    if hasattr(frame, 'get'):  # OpenCV UMat
                        frame = frame.get()
                    
                    # 将图像转换为JPEG
                    ret, buffer = cv2.imencode('.jpg', frame)
                    if not ret:
                        logger.warning(f"无法编码视频帧")
                        time.sleep(0.1)
                        continue
                    
                    jpeg_bytes = buffer.tobytes()
                    
                    # 生成MJPEG格式的视频帧
                    yield (b'--frame\r\n' 
                           b'Content-Type: image/jpeg\r\n\r\n' + jpeg_bytes + b'\r\n\r\n')
                    
                    # 控制帧率
                    time.sleep(0.1)  # 约10fps
                    
                except Exception as e:
                    logger.warning(f"视频流生成错误: {str(e)}")
                    time.sleep(0.5)
                    break
        
        # 返回MJPEG格式的视频流
        return Response(generate(), 
                       mimetype='multipart/x-mixed-replace; boundary=frame')
        
    except Exception as e:
        logger.error(f"视频流推送失败: {str(e)}")
        return jsonify({"error": "视频流推送失败"}), 500

@cameras_bp.route('/<int:camera_id>/config', methods=['GET'])
@token_required
def get_camera_config(camera_id):
    """获取摄像头配置
    
    GET /api/cameras/<camera_id>/config
    
    获取指定摄像头的详细配置信息
    """
    try:
        # 从数据库获取摄像头配置
        camera = db_service.get_camera_by_id(camera_id)
        if not camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 提取配置信息
        config_str = camera.config if hasattr(camera, 'config') else camera.get('config', '{}')
        config = json.loads(config_str) if isinstance(config_str, str) else config_str
        
        # 从视频管理器获取运行时配置
        runtime_config = {}
        video_mgr = _get_video_manager()
        if video_mgr and hasattr(video_mgr, 'get_camera_runtime_config'):
            runtime_config = video_mgr.get_camera_runtime_config(camera_id)
        
        return jsonify({
            "camera_id": camera_id,
            "config": config,
            "runtime_config": runtime_config,
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"获取摄像头配置失败: {str(e)}")
        return jsonify({"error": "获取摄像头配置失败"}), 500

@cameras_bp.route('/<int:camera_id>/config', methods=['PUT'])
@token_required
def update_camera_config(camera_id):
    """更新摄像头配置
    
    PUT /api/cameras/<camera_id>/config
    
    更新指定摄像头的配置信息
    """
    try:
        # 获取请求数据
        data = request.get_json()
        
        # 检查摄像头是否存在
        existing_camera = db_service.get_camera_by_id(camera_id)
        if not existing_camera:
            return jsonify({"error": "摄像头不存在"}), 404
        
        # 更新数据库中的配置
        db_service.update_camera(camera_id, {
            'config': json.dumps(data),
            'updated_at': datetime.now(),
            'updated_by': request.user_id
        })
        
        # 更新视频管理器中的配置
        video_mgr = _get_video_manager()
        if video_mgr and hasattr(video_mgr, 'update_camera_config'):
            try:
                video_mgr.update_camera_config(camera_id, data)
            except Exception as e:
                logger.warning(f"更新摄像头运行时配置失败: {str(e)}")
        
        return jsonify({
            "message": "摄像头配置更新成功",
            "camera_id": camera_id,
            "timestamp": datetime.now().isoformat()
        }), 200
        
    except Exception as e:
        logger.error(f"更新摄像头配置失败: {str(e)}")
        return jsonify({"error": "更新摄像头配置失败"}), 500
    """获取摄像头列表
    
    查询参数:
    - status: 过滤状态 (active/inactive)
    - enabled: 过滤启用状态 (true/false)
    
    返回:
    - 摄像头列表
    """
    try:
        # 获取查询参数
        status = request.args.get('status')
        enabled = request.args.get('enabled')
        
        # 构建过滤条件
        filters = {}
        if status:
            filters['status'] = status
        if enabled is not None:
            filters['is_enabled'] = enabled.lower() == 'true'
        
        # 获取摄像头列表
        cameras = camera_manager.get_cameras(**filters)
        
        # 转换为字典格式
        result = []
        for cam in cameras:
            camera_dict = {
                'id': cam.id,
                'name': cam.name,
                'url': cam.url,
                'type': cam.camera_type,
                'status': cam.status,
                'enabled': cam.is_enabled,
                'location': cam.location,
                'description': cam.description,
                'created_at': cam.created_at.isoformat() if cam.created_at else None,
                'updated_at': cam.updated_at.isoformat() if cam.updated_at else None,
                'roi': cam.roi if hasattr(cam, 'roi') else None
            }
            result.append(camera_dict)
        
        return jsonify({
            'cameras': result,
            'total': len(result)
        })
    except Exception as e:
        logger.error(f"获取摄像头列表失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>', methods=['GET'])
def get_camera(camera_id):
    """获取单个摄像头信息
    
    参数:
    - camera_id: 摄像头ID
    
    返回:
    - 摄像头详细信息
    """
    try:
        camera = camera_manager.get_camera_by_id(camera_id)
        if not camera:
            return jsonify({'error': '摄像头不存在'}), 404
        
        return jsonify({
            'id': camera.id,
            'name': camera.name,
            'url': camera.url,
            'type': camera.camera_type,
            'status': camera.status,
            'enabled': camera.is_enabled,
            'location': camera.location,
            'description': camera.description,
            'created_at': camera.created_at.isoformat() if camera.created_at else None,
            'updated_at': camera.updated_at.isoformat() if camera.updated_at else None,
            'roi': camera.roi if hasattr(camera, 'roi') else None,
            'settings': camera.settings if hasattr(camera, 'settings') else {}
        })
    except Exception as e:
        logger.error(f"获取摄像头信息失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/', methods=['POST'])
def add_camera():
    """添加新摄像头
    
    Body参数:
    - name: 摄像头名称
    - url: 摄像头URL或设备ID
    - type: 摄像头类型 (rtsp/webcam/file)
    - location: 摄像头位置
    - description: 摄像头描述
    - roi: 感兴趣区域 [{"x": 0, "y": 0, "width": 640, "height": 480}]
    - settings: 摄像头设置
    
    返回:
    - 新创建的摄像头信息
    """
    try:
        data = request.json
        if not data:
            return jsonify({'error': '请求体不能为空'}), 400
        
        # 验证必要字段
        required_fields = ['name', 'url', 'type']
        for field in required_fields:
            if field not in data:
                return jsonify({'error': f'{field} 是必填字段'}), 400
        
        # 添加摄像头
        camera = camera_manager.add_camera(data)
        
        logger.info(f"添加摄像头成功: {camera.name} (ID: {camera.id})")
        
        return jsonify({
            'id': camera.id,
            'name': camera.name,
            'url': camera.url,
            'type': camera.camera_type,
            'status': camera.status,
            'enabled': camera.is_enabled
        }), 201
    except ValueError as e:
        logger.warning(f"添加摄像头失败: {str(e)}")
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        logger.error(f"添加摄像头失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>', methods=['PUT'])
def update_camera(camera_id):
    """更新摄像头信息
    
    参数:
    - camera_id: 摄像头ID
    
    Body参数:
    - name: 摄像头名称
    - url: 摄像头URL或设备ID
    - location: 摄像头位置
    - description: 摄像头描述
    - roi: 感兴趣区域
    - settings: 摄像头设置
    
    返回:
    - 更新后的摄像头信息
    """
    try:
        data = request.json
        if not data:
            return jsonify({'error': '请求体不能为空'}), 400
        
        # 更新摄像头
        camera = camera_manager.update_camera(camera_id, data)
        if not camera:
            return jsonify({'error': '摄像头不存在'}), 404
        
        logger.info(f"更新摄像头成功: {camera.name} (ID: {camera.id})")
        
        return jsonify({
            'id': camera.id,
            'name': camera.name,
            'url': camera.url,
            'type': camera.camera_type,
            'status': camera.status,
            'enabled': camera.is_enabled
        })
    except ValueError as e:
        logger.warning(f"更新摄像头失败: {str(e)}")
        return jsonify({'error': str(e)}), 400
    except Exception as e:
        logger.error(f"更新摄像头失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>', methods=['DELETE'])
def delete_camera(camera_id):
    """删除摄像头
    
    参数:
    - camera_id: 摄像头ID
    
    返回:
    - 删除结果
    """
    try:
        # 先停止摄像头
        camera_manager.stop_camera(camera_id)
        
        # 删除摄像头
        success = camera_manager.remove_camera(camera_id)
        if not success:
            return jsonify({'error': '摄像头不存在'}), 404
        
        logger.info(f"删除摄像头成功: ID {camera_id}")
        
        return jsonify({'status': 'success', 'message': '摄像头已删除'})
    except Exception as e:
        logger.error(f"删除摄像头失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>/start', methods=['POST'])
def start_camera(camera_id):
    """启动摄像头
    
    参数:
    - camera_id: 摄像头ID
    
    返回:
    - 启动结果
    """
    try:
        success = camera_manager.start_camera(camera_id)
        if not success:
            return jsonify({'error': '摄像头不存在或启动失败'}), 404
        
        logger.info(f"启动摄像头成功: ID {camera_id}")
        
        return jsonify({'status': 'started', 'message': '摄像头已启动'})
    except Exception as e:
        logger.error(f"启动摄像头失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>/stop', methods=['POST'])
def stop_camera(camera_id):
    """停止摄像头
    
    参数:
    - camera_id: 摄像头ID
    
    返回:
    - 停止结果
    """
    try:
        success = camera_manager.stop_camera(camera_id)
        if not success:
            return jsonify({'error': '摄像头不存在或停止失败'}), 404
        
        logger.info(f"停止摄像头成功: ID {camera_id}")
        
        return jsonify({'status': 'stopped', 'message': '摄像头已停止'})
    except Exception as e:
        logger.error(f"停止摄像头失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>/snapshot', methods=['GET'])
def get_camera_snapshot(camera_id):
    """获取摄像头快照
    
    参数:
    - camera_id: 摄像头ID
    - with_overlay: 是否包含检测覆盖层 (true/false)
    
    返回:
    - 图像数据 (JPEG格式)
    """
    try:
        with_overlay = request.args.get('with_overlay', 'false').lower() == 'true'
        
        # 获取摄像头
        camera = camera_manager.get_camera_by_id(camera_id)
        if not camera:
            return jsonify({'error': '摄像头不存在'}), 404
        
        if camera.status != 'active':
            return jsonify({'error': '摄像头未激活'}), 400
        
        # 获取最新帧
        frame = camera_manager.get_latest_frame(camera_id)
        if frame is None:
            return jsonify({'error': '无法获取图像帧'}), 500
        
        # 如果需要覆盖层，应用检测结果
        if with_overlay:
            # 这里应该调用frame_processor来绘制检测结果
            # 简化处理，直接返回原始帧
            pass
        
        # 将帧转换为JPEG
        _, buffer = cv2.imencode('.jpg', frame)
        if not _:
            return jsonify({'error': '无法编码图像'}), 500
        
        # 返回图像数据
        return Response(buffer.tobytes(), mimetype='image/jpeg')
    except Exception as e:
        logger.error(f"获取摄像头快照失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>/snapshot/base64', methods=['GET'])
def get_camera_snapshot_base64(camera_id):
    """获取摄像头快照 (Base64格式)
    
    参数:
    - camera_id: 摄像头ID
    - with_overlay: 是否包含检测覆盖层 (true/false)
    
    返回:
    - Base64编码的图像数据
    """
    try:
        with_overlay = request.args.get('with_overlay', 'false').lower() == 'true'
        
        # 获取摄像头
        camera = camera_manager.get_camera_by_id(camera_id)
        if not camera:
            return jsonify({'error': '摄像头不存在'}), 404
        
        if camera.status != 'active':
            return jsonify({'error': '摄像头未激活'}), 400
        
        # 获取最新帧
        frame = camera_manager.get_latest_frame(camera_id)
        if frame is None:
            return jsonify({'error': '无法获取图像帧'}), 500
        
        # 如果需要覆盖层，应用检测结果
        if with_overlay:
            # 这里应该调用frame_processor来绘制检测结果
            # 简化处理，直接返回原始帧
            pass
        
        # 将帧转换为JPEG并编码为Base64
        _, buffer = cv2.imencode('.jpg', frame)
        if not _:
            return jsonify({'error': '无法编码图像'}), 500
        
        img_str = base64.b64encode(buffer.tobytes()).decode('utf-8')
        
        return jsonify({
            'image': img_str,
            'timestamp': time.time(),
            'camera_id': camera_id
        })
    except Exception as e:
        logger.error(f"获取摄像头快照(Base64)失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/<int:camera_id>/stream', methods=['GET'])
def get_camera_stream(camera_id):
    """获取摄像头视频流 (MJPEG格式)
    
    参数:
    - camera_id: 摄像头ID
    - with_overlay: 是否包含检测覆盖层 (true/false)
    - fps: 帧率限制
    
    返回:
    - MJPEG视频流
    """
    try:
        # 验证摄像头存在且激活
        camera = camera_manager.get_camera_by_id(camera_id)
        if not camera:
            return jsonify({'error': '摄像头不存在'}), 404
        
        if camera.status != 'active':
            return jsonify({'error': '摄像头未激活'}), 400
        
        # 获取请求参数
        with_overlay = request.args.get('with_overlay', 'false').lower() == 'true'
        fps = int(request.args.get('fps', 15))
        
        # 生成视频流
        def generate_stream():
            interval = 1.0 / fps
            last_frame_time = 0
            
            while True:
                current_time = time.time()
                
                # 控制帧率
                if current_time - last_frame_time < interval:
                    time.sleep(interval - (current_time - last_frame_time))
                
                last_frame_time = time.time()
                
                try:
                    # 获取最新帧
                    frame = camera_manager.get_latest_frame(camera_id)
                    if frame is None:
                        continue
                    
                    # 如果需要覆盖层，应用检测结果
                    if with_overlay:
                        # 这里应该调用frame_processor来绘制检测结果
                        # 简化处理，直接使用原始帧
                        pass
                    
                    # 编码为JPEG
                    _, buffer = cv2.imencode('.jpg', frame)
                    if not _:
                        continue
                    
                    # 生成MJPEG流
                    frame_bytes = buffer.tobytes()
                    yield (
                        b'--frame\r\n'
                        b'Content-Type: image/jpeg\r\n'
                        b'Content-Length: ' + str(len(frame_bytes)).encode() + b'\r\n'
                        b'\r\n' + frame_bytes + b'\r\n'
                    )
                except Exception as e:
                    logger.error(f"视频流生成错误: {str(e)}")
                    time.sleep(1)  # 避免CPU占用过高
        
        return Response(generate_stream(), mimetype='multipart/x-mixed-replace; boundary=frame')
    except Exception as e:
        logger.error(f"获取摄像头视频流失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/batch/start', methods=['POST'])
def start_batch_cameras():
    """批量启动摄像头
    
    Body参数:
    - camera_ids: [1, 2, 3] 摄像头ID列表
    
    返回:
    - 批量操作结果
    """
    try:
        data = request.json or {}
        camera_ids = data.get('camera_ids', [])
        
        if not isinstance(camera_ids, list):
            return jsonify({'error': 'camera_ids 必须是数组'}), 400
        
        results = {
            'success': [],
            'failed': []
        }
        
        for camera_id in camera_ids:
            try:
                if camera_manager.start_camera(camera_id):
                    results['success'].append(camera_id)
                else:
                    results['failed'].append({camera_id: '启动失败'})
            except Exception as e:
                results['failed'].append({camera_id: str(e)})
        
        return jsonify({
            'status': 'completed',
            'results': results,
            'total_processed': len(camera_ids),
            'total_success': len(results['success']),
            'total_failed': len(results['failed'])
        })
    except Exception as e:
        logger.error(f"批量启动摄像头失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500

@cameras_bp.route('/batch/stop', methods=['POST'])
def stop_batch_cameras():
    """批量停止摄像头
    
    Body参数:
    - camera_ids: [1, 2, 3] 摄像头ID列表
    
    返回:
    - 批量操作结果
    """
    try:
        data = request.json or {}
        camera_ids = data.get('camera_ids', [])
        
        if not isinstance(camera_ids, list):
            return jsonify({'error': 'camera_ids 必须是数组'}), 400
        
        results = {
            'success': [],
            'failed': []
        }
        
        for camera_id in camera_ids:
            try:
                if camera_manager.stop_camera(camera_id):
                    results['success'].append(camera_id)
                else:
                    results['failed'].append({camera_id: '停止失败'})
            except Exception as e:
                results['failed'].append({camera_id: str(e)})
        
        return jsonify({
            'status': 'completed',
            'results': results,
            'total_processed': len(camera_ids),
            'total_success': len(results['success']),
            'total_failed': len(results['failed'])
        })
    except Exception as e:
        logger.error(f"批量停止摄像头失败: {str(e)}")
        return jsonify({'error': f'服务器内部错误: {str(e)}'}), 500